﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Boggle;
using System.Threading;

namespace BoggleClientTest
{
    /// <summary>
    /// Summary description for UnitTest1
    /// </summary>
    [TestClass]
    public class UnitTest1
    {
        public UnitTest1()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        public void TestMethod1()
        {
            new test1Class().run();
        }

        public class test1Class
        {
            BoggleServer server;
            BoggleConnector player1, player2;
            ManualResetEvent mre1, mre2,mreForTime,mreIgnore,mreStop,mreTerminated,mreClosed,mreConnected;
            string[] stopString;

            public void run()
            {
                
              
                mre1 = new ManualResetEvent(false);
                mre2 = new ManualResetEvent(false);
                mreForTime = new ManualResetEvent(false);
                mreIgnore = new ManualResetEvent(false);
                mreStop = new ManualResetEvent(false);
                mreTerminated = new ManualResetEvent(false);
                mreClosed = new ManualResetEvent(false);
                mreConnected = new ManualResetEvent(false);
                

                player1 = new BoggleConnector("Adam");
                player2 = new BoggleConnector("Tim");
                player1.Connected += new ConnectedHandler(player1_Connected);
                player1.ConnectionFailed += new ConnectionFailedHandler(player1_ConnectionFailed);
                player1.TimeChanged += new TimeChangedHandler(player1_TimeChanged);
                player1.ConnectToServer("localhost");
                mre1.WaitOne(2000);
                

                server = new BoggleServer(4, "..//..//..//dictionary.txt", "XDEBATNFSUOPMLRL");
                Thread.Sleep(500);

                player1.GameStarted += new GameStartedHandler(player1_GameStarted);
                player1.ScoreChanged += new ScoreChangedHandler(player1_ScoreChanged);
                player2.GameStarted += new GameStartedHandler(player2_GameStarted);
                player2.ScoreChanged += new ScoreChangedHandler(player2_ScoreChanged);

                Assert.IsTrue(player1.ConnectToServer("localhost"));
                Assert.IsTrue(player2.ConnectToServer("localhost"));

                Assert.IsTrue(mreConnected.WaitOne(2000));

                mre1.WaitOne();
                mre2.WaitOne();
                mre1.Reset();
                mre2.Reset();

                //check that the timer works.
                mreForTime.WaitOne(2000);


                Assert.AreEqual(player1.OpponentName, "Tim");
                Assert.AreEqual(player2.OpponentName, "Adam");

                Assert.AreEqual(player1.Board, player2.Board);
                Assert.AreEqual(player1.Board, "XDEBATNFSUOPMLRL");

                player1.SendMessage("WORD GOOSE\n");
                player2.SendMessage("WORD POUND\n");

                Assert.IsTrue( mre1.WaitOne(2000));
                Assert.IsTrue( mre2.WaitOne(2000));
                {
                    Assert.AreEqual(player1.Score1, -1);
                    Assert.AreEqual(player2.Score1, 2);
                    Assert.AreEqual(player2.Score1, 2);
                    Assert.AreEqual(player1.Score1, -1);
                }


                player1.SendMessage("WORD BETS\n");
                player1.SendMessage("WORD MUST\n");
                player2.SendMessage("WORD MUST\n");
                player2.SendMessage("WORD SCHLONG\n");

                //check the ignore callback
                player1.Ignored += new IgnoringHandler(player1_Ignored);
                player1.SendMessage("Sup Bro!\n");
                Assert.IsTrue(mreIgnore.WaitOne(2000));
               

                //check the Stop callback
                player1.GameStopped += new GameStoppedHandler(player1_GameStopped);
                Assert.IsTrue(mreStop.WaitOne(4000));
                Assert.AreEqual(stopString[0], "");
                Assert.AreEqual(stopString[1], "BETS");
                Assert.AreEqual(stopString[2], "POUND");
                Assert.AreEqual(stopString[3], "MUST");
                Assert.AreEqual(stopString[4], "GOOSE");
                Assert.AreEqual(stopString[5], "SCHLONG");
                
                

                //check the terminated event
                player1 = new BoggleConnector("Adam");
                player2 = new BoggleConnector("Tim");
                Assert.IsTrue(player1.ConnectToServer("localhost"));
                Assert.IsTrue(player2.ConnectToServer("localhost"));

                mre1.WaitOne();
                mre2.WaitOne();
                mre1.Reset();
                mre2.Reset();
                player1.Terminated += new TerminatedHandler(player1_Terminated);
                player2.ConnectionClosed += new GameEndedHandler(player2_ConnectionClosed);
                player2.CloseConnection();
                mreTerminated.WaitOne(2000);
                Assert.IsTrue(mreClosed.WaitOne(2000));

                


                


            }

            void player1_Connected(object sender, EventArgs e)
            {
                mreConnected.Set();
            }

            void player2_ConnectionClosed(object sender, EventArgs e)
            {
                mreClosed.Set();
            }

            
            void player1_Terminated(object sender, EventArgs e)
            {
                mreTerminated.Set();
            }

            void player1_GameStopped(object sender, ArrayEventArgs e)
            {
                stopString = e.strings;
                mreStop.Set();
                
            }

            void player1_Ignored(object sender, StringEventArgs e)
            {
                mreIgnore.Set();
            }

            void player1_TimeChanged(object sender, StringEventArgs e)
            {
                mreForTime.Set();
            }

            void player1_ConnectionFailed(object sender, EventArgs e)
            {
                mre1.Set();
            }

           
            //score changed event handelers
            void player1_ScoreChanged(object sender, ArrayEventArgs e)
            {
                mre1.Set();
            }
            void player2_ScoreChanged(object sender, ArrayEventArgs e)
            {
                mre2.Set();
            }

            
            //game started event handelers.
            void player1_GameStarted(object sender, ArrayEventArgs e)
            {
                mre1.Set();
            }
            void player2_GameStarted(object sender, ArrayEventArgs e)
            {
                mre2.Set();
            }
        }
    }
}
